#ifndef __SETTINGS_HH
#define __SETTINGS_HH

#include <iostream>
#include <fstream>
#include <string>

#include "TSystem.h"
#include "TEnv.h"

using namespace std;

class Settings {
public:
  Settings();//default ctor
  Settings(const char*);
  ~Settings();

  void ReadSettings();
  void PrintSettings();
  void SetFile(const char* filename){
    fInputFile = filename;
  }
  const string InputFile(){
    return fInputFile;
  };

  int VLevel(){
    return fVerboseLevel;
  }

  double MinimalStripRatio(int quadr){
    return fMinimalStripRatio;
  }
  double MinimalStripRearRatio(int quadr){
    return fMinimalStripRearRatio;
  }
  double CDTBLowerThresh(){
    return fCDTBLowerThresh;
  }
  double CDTBUpperThresh(){
    return fCDTBUpperThresh;
  }
  double CDLRLowerThresh(){
    return fCDLRLowerThresh;
  }
  double CDLRUpperThresh(){
    return fCDLRUpperThresh;
  }
  double CDLowerThreshRing(int quadr){
    switch(quadr){
    case 0: // top
      return fCDTBLowerThresh;
      break;
    case 1: // left
      return fCDLRLowerThresh;
      break;
    case 2: // bottom
      return fCDTBLowerThresh;
      break;
    case 3: // right
      return fCDLRLowerThresh;
      break;
    default:
      break;    
    }
  }
  /*
  // ******* 2009 *******
  double CDLowerThreshStrip(int quadr){
    switch(quadr){
    case 0: // top
      return fCDLRLowerThresh;
      break;
    case 1: // left
      return fCDTBLowerThresh;
      break;
    case 2: // bottom
      return fCDLRLowerThresh;
      break;
    case 3: // right
      return fCDTBLowerThresh;
      break;
    default:
      break;    
    }
  }
  */
  // ******* 2010 *******
  double CDLowerThreshStrip(int quadr){
    switch(quadr){
    case 0: // top
      return fCDTBLowerThresh;
      break;
    case 1: // left
      return fCDLRLowerThresh;
      break;
    case 2: // bottom
      return fCDTBLowerThresh;
      break;
    case 3: // right
      return fCDLRLowerThresh;
      break;
    default:
      break;    
    }
  }
  double CDUpperThreshRing(int quadr){
    switch(quadr){
    case 0: // top
      return fCDTBUpperThresh;
      break;
    case 1: // left
      return fCDLRUpperThresh;
      break;
    case 2: // bottom
      return fCDTBUpperThresh;
      break;
    case 3: // right
      return fCDLRUpperThresh;
      break;
    default:
      break;    
    }
  }
  /*
  // ***** 2009 *******
  double CDUpperThreshStrip(int quadr){
    switch(quadr){
    case 0: // top
      return fCDLRUpperThresh;
      break;
    case 1: // left
      return fCDTBUpperThresh;
      break;
    case 2: // bottom
      return fCDLRUpperThresh;
      break;
    case 3: // right
      return fCDTBUpperThresh;
      break;
    default:
      break;    
    }
  }
  */
  // ***** 2010 *******
  double CDUpperThreshStrip(int quadr){
    switch(quadr){
    case 0: // top
      return fCDTBUpperThresh;
      break;
    case 1: // left
      return fCDLRUpperThresh;
      break;
    case 2: // bottom
      return fCDTBUpperThresh;
      break;
    case 3: // right
      return fCDLRUpperThresh;
      break;
    default:
      break;    
    }
  }
  int RearECDMod(int quadr){
    return fRearECDMod[quadr];
  }
  int RearECDModRing(int quadr){
    return fRearECDModRing[quadr];
  }
  int RearECDModStrip(int quadr){
    return fRearECDModStrip[quadr];
  }

  int FDeltaChan(int quadr){
    return fFDeltaChan[quadr];
  }
  int BDeltaChan(int quadr){
    return fBDeltaChan[quadr];
  }
  int FDeltaThresh(int quadr){
    return fFDeltaThresh[quadr];
  }
  int BDeltaThresh(int quadr){
    return fBDeltaThresh[quadr];
  }
  int FEChan(int quadr){
    return fFEChan[quadr];
  }
  int BEChan(int quadr){
    return fBEChan[quadr];
  }
  int FEThresh(int quadr){
    return fFEThresh[quadr];
  }
  int BEThresh(int quadr){
    return fBEThresh[quadr];
  }
  int FStripMod(int quadr){
    return fFStripMod[quadr];
  }
  int BStripMod(int quadr){
    return fBStripMod[quadr];
  }
  int FFirstStrip(int quadr){
    return fFFirstStrip[quadr];
  }
  int BFirstStrip(int quadr){
    return fBFirstStrip[quadr];
  }
  double FEGainFactor(int quadr){
    return fFEGainFactor[quadr];
  }
  int NofDgfs(){
    return fNofDgfs;
  }
  int NofDgfChans(){
    return fNofDgfChans;
  }
  int NofAdcs(){
    return fNofAdcs;
  }
  int NofAdcChans(){
    return fNofAdcChans;
  }
  int BeamdumpDgf(){
    return fBeamdumpDgf;
  }
  int CDRingEnergy(int half, int hit){
    return fCDRingEnergy[half][hit];
  }
  int CDRingPos(int half, int hit){
    return fCDRingPosition[half][hit];
  }
  int CDStripEnergy(int half, int hit){
    return fCDStripEnergy[half][hit];
  }
  int CDStripPos(int half, int hit){
    return fCDStripPosition[half][hit];
  }
  int CDEChan(int quadr){
    return fCDEChan[quadr];
  }
  int CDDeltaThreshRing(int half){
    return fCDDeltaThreshRing[half];
  }
  int CDDeltaThreshStrip(int half){
    return fCDDeltaThreshStrip[half];
  }

  //miniball stuff
  int FirstDgf(int cluster){
    return fFirstDgf[cluster];
  }
  int CoreChannel(){
    return fCoreChannel;
  }
  int Cluster(int modnr){
    for(int i=0;i<8;i++){
      //cout << i << " fFirstDgf[i] " << fFirstDgf[i] << " fFirstDgf[i+1] " << fFirstDgf[i+1] << endl;  
      //cout << "modnr " << modnr << endl;
      if( fFirstDgf[i] <= modnr && modnr< fFirstDgf[i+1] ){
	//cout << "settings cluster " << i << endl;
	return i;
      }
    }
    return -1;
  }
  int Crystal(int modnr){ // two modules per crystal
    modnr-=fFirstDgf[Cluster(modnr)]; // value between 0 and 5
    //0 A, 1 A, 2 B
    //3 B, 4 C, 5 C
    return modnr/2; //0 A, 1 B, 2 C    
  }
  int Segment(int modnr, int chan){
    //first dgf: core, 0, 1, nothing
    //secon dgf: 2, 3, 4, 5
    modnr-=fFirstDgf[Cluster(modnr)];
    if(modnr%2==0){ // first module
      if(chan==3){
	cerr << "Error in Cluster " << Cluster(modnr) << " Module Nr. " << modnr << " of that Cluster, Channel 3 is not connected." << endl;
	return -1;
      }
      else if(chan==0){
	cerr << "@@@@@@@@@@@@@@@ This is a core channel, trying to get seg id @@@@@@@@@@" << endl; 
	return -1;
      }
      else
	return chan - 1;
    }
    else{
      return chan + 2;
    } 
  }
  int DgfThresh(){
    return fDgfThresh;
  }
  
protected:

  int fVerboseLevel;

  string fInputFile;
  double fMinimalStripRatio;
  double fMinimalStripRearRatio;
  double fCDTBLowerThresh;
  double fCDTBUpperThresh;
  double fCDLRLowerThresh;
  double fCDLRUpperThresh;

  int fRearECDMod[4];
  int fRearECDModRing[4];
  int fRearECDModStrip[4];

  int fFDeltaChan[4];
  int fBDeltaChan[4];
  int fFDeltaThresh[4];
  int fBDeltaThresh[4];
  int fFEChan[4];
  int fBEChan[4];
  int fFEThresh[4];
  int fBEThresh[4];
  int fFStripMod[4];
  int fBStripMod[4];
  int fFFirstStrip[4];
  int fBFirstStrip[4];

  double fFEGainFactor[4];

  int fCDRingEnergy[2][2];
  int fCDRingPosition[2][2];
  int fCDStripEnergy[2][2];
  int fCDStripPosition[2][2];

  int fCDDeltaThreshRing[2];
  int fCDDeltaThreshStrip[2];
  int fCDEChan[4];

  int fNofDgfs;
  int fNofDgfChans;
  int fNofAdcs;
  int fNofAdcChans;
  int fBeamdumpDgf;
  
  int fFirstDgf[9];
  int fCoreChannel;
  int fDgfThresh;
  //ClassDef(Settings, 1)
};

#endif
